﻿using System;
using UnityEngine.UI;
using UnityEngine;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;

using VFramework;

public class Util
{


	public delegate void _ActionFunc (object obj);

	/// <summary>
	/// result是否包含entity，作为前缀
	/// </summary>
	/// <returns><c>true</c>, if is equal was prefixed, <c>false</c> otherwise.</returns>
	/// <param name="entity">前缀</param>
	/// <param name="result">全串</param>
	/// <param name="isIgnoreSeq">是否按顺序</param>
	public static bool prefixIsEqual (string entity, string result, bool isIgnoreSeq = false)
	{

		if (entity.Length > result.Length)
			return false;

		if (isIgnoreSeq) {
			string sub = result.Substring (0, entity.Length);
			Dictionary<char, bool> isHave = new Dictionary<char, bool> ();
			foreach (char c in sub)
				isHave.Add (c, true);

			foreach (char c in entity) {
				if (!isHave.ContainsKey (c))
					return false;
			}
			return true;

		} else {
			foreach (char c in entity) {
				int index = entity.IndexOf (c);
				if (c != result [index])
					return false;
			}
			return true;
		}

	}

	/// <summary>
	/// 获取命令行启动的参数列表 -userid=1
	/// <para> cmdLine 命令行全部参数 ./xxx -userid=333 -ssid=22323 -ip=192.168.1.178:1000
	/// </summary>
	/// <returns>The cmd line dic.</returns>
	public static Dictionary<string, string> getCmdLineDic (string cmdLine)
	{
		Dictionary<string, string> args = new Dictionary<string, string> ();
		string [] fa = cmdLine.Split (' ');
		if (fa.Length <= 1) {
			return args;
		}

		for (int i = 1; i < fa.Length; i++) {
			try {
				string key = fa [i].Split ('=') [0].Substring (1);
				string value = fa [i].Split ('=') [1];
				args.Add (key, value);
			} catch (Exception e) {
				VLogger.error (e.ToString ());
			}
		}
		return args;
	}

	public static IEnumerator DelayRun (_ActionFunc func, float time, object arg = null)
	{
		yield return new WaitForSeconds (time);
		func.Invoke (arg);
	}

	private static int rep = 0;

	public static long timeStamp ()
	{
		System.TimeSpan ts = System.DateTime.UtcNow - new System.DateTime (1970, 1, 1, 0, 0, 0, 0);
		return System.Convert.ToInt64 (ts.TotalSeconds);
	}


	public static DateTime GetTime (string timeStamp)
	{
		DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime (new DateTime (1970, 1, 1));
		long lTime = long.Parse (timeStamp + "0000000");
		TimeSpan toNow = new TimeSpan (lTime);
		return dtStart.Add (toNow);
	}


	public static long ConvertDateTimeInt (System.DateTime time)
	{
		System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime (new System.DateTime (1970, 1, 1));
		return System.Convert.ToInt64 ((time - startTime).TotalSeconds);
	}

	public static string nowTimeymd ()
	{
		return getTimeStrByFMT ("yyyy-MM-dd HH:mm:ss", System.DateTime.Now);
	}

	public static string getTimeStrByFMT (string fmt, DateTime dateTime)
	{
		return dateTime.ToString (fmt, System.Globalization.DateTimeFormatInfo.InvariantInfo);
	}


	public static void setAlpha (Image img)
	{
		Color c = img.color;
		img.color = new Color (c.r, c.g, c.b, 0);
	}

	public static Canvas getCanvas (GameObject obj)
	{

		Transform t = obj.transform.parent;
		while (t != null) {
			if (t.GetComponent<Canvas> () != null) {
				return t.GetComponent<Canvas> ();
			}
			t = t.parent;
		}

		return null;

	}

	public static string genTerm (int offset = 0)
	{
		DateTime now = DateTime.Now;
		return now.ToString ("MMdd") + (now.Hour * 30 + (now.Minute - offset)).ToString ().PadLeft (3, '0');
	}

	public static string getRanomString (int codeCount)
	{
		string str = string.Empty;
		long num2 = DateTime.Now.Ticks + (Util.rep++);

		System.Random random = new System.Random (((int)(((ulong)num2) & 0xffffffffL)) | ((int)(num2 >> Util.rep)));
		for (int i = 0; i < codeCount; i++) {
			char ch;
			int num = random.Next ();
			if ((num % 2) == 0) {
				ch = (char)(0x30 + ((ushort)(num % 10)));
			} else {
				ch = (char)(0x41 + ((ushort)(num % 0x1a)));
			}
			str = str + ch.ToString ();
		}
		return str;
	}

	// comb(5,2) = 1
	public static int comb (int n, int m)
	{
		if (m > n) {
			throw new Exception ("m > n ??");
		}

		if (m == 0 || n == m)
			return 1;
		return comb (n - 1, m - 1) + comb (n - 1, m);
	}






	public static long GetTime ()
	{
		TimeSpan ts = new TimeSpan (DateTime.UtcNow.Ticks - new DateTime (1970, 1, 1, 0, 0, 0).Ticks);
		return (long)ts.TotalMilliseconds;
	}





	/// <summary>
	/// Base64编码
	/// </summary>
	public static string Encode (string message)
	{
		byte [] bytes = Encoding.GetEncoding ("utf-8").GetBytes (message);
		return Convert.ToBase64String (bytes);
	}

	/// <summary>
	/// Base64解码
	/// </summary>
	public static string Decode (string message)
	{
		byte [] bytes = Convert.FromBase64String (message);
		return Encoding.GetEncoding ("utf-8").GetString (bytes);
	}


	/// <summary>
	/// HashToMD5Hex
	/// </summary>
	public static string HashToMD5Hex (string sourceStr)
	{
		byte [] Bytes = Encoding.UTF8.GetBytes (sourceStr);
		using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider ()) {
			byte [] result = md5.ComputeHash (Bytes);
			StringBuilder builder = new StringBuilder ();
			for (int i = 0; i < result.Length; i++)
				builder.Append (result [i].ToString ("x2"));
			return builder.ToString ();
		}
	}

	/// <summary>
	/// 计算字符串的MD5值
	/// </summary>
	public static string MD5 (string source)
	{
		MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider ();
		byte [] data = System.Text.Encoding.UTF8.GetBytes (source);
		byte [] md5Data = md5.ComputeHash (data, 0, data.Length);
		md5.Clear ();

		string destString = "";
		for (int i = 0; i < md5Data.Length; i++) {
			destString += System.Convert.ToString (md5Data [i], 16).PadLeft (2, '0');
		}
		destString = destString.PadLeft (32, '0');
		return destString;
	}

	/// <summary>
	/// 计算文件的MD5值
	/// </summary>
	public static string md5file (string file)
	{
		try {
			FileStream fs = new FileStream (file, FileMode.Open);
			System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider ();
			byte [] retVal = md5.ComputeHash (fs);
			fs.Close ();

			StringBuilder sb = new StringBuilder ();
			for (int i = 0; i < retVal.Length; i++) {
				sb.Append (retVal [i].ToString ("x2"));
			}
			return sb.ToString ();
		} catch (Exception ex) {
			throw new Exception ("md5file() fail, error:" + ex.Message);
		}
	}

	/// <summary>
	/// Gets the bytes.
	/// </summary>
	/// <returns>The bytes.</returns>
	/// <param name="source">Source.</param>
	public static byte [] GetBytes (string source)
	{
		byte [] bs = System.Text.Encoding.UTF8.GetBytes (source);
		return bs;
	}

	/// <summary>
	/// 加密
	/// </summary>
	/// <param name="pData">P data.</param>
	public static void Encrypt (ref byte [] pData)
	{
		for (int i = 0; i < pData.Length; i++) {
			int b = Convert.ToInt32 (pData [i]);
			b = b ^ 0xa5;
			b = b << 4 | b >> 4;
			pData [i] = (byte)b;
		}
	}

	/// <summary>
	/// 解密
	/// </summary>
	/// <param name="pData">P data.</param>
	public static void UnEncrypt (ref byte [] pData)
	{
		for (int i = 0; i < pData.Length; i++) {
			int b = Convert.ToInt32 (pData [i]);
			b = b << 4 | b >> 4;
			b = b ^ 0xa5;
			pData [i] = (byte)b;
		}
	}


	/// <summary>
	/// 清理内存
	/// </summary>
	public static void ClearMemory ()
	{
		GC.Collect ();
		Resources.UnloadUnusedAssets ();
	}

	/// <summary>
	/// 是否为数字
	/// </summary>
	public static bool IsNumber (string strNumber)
	{
		Regex regex = new Regex ("[^0-9]");
		return !regex.IsMatch (strNumber);
	}



	/// <summary>
	/// 取得行文本
	/// </summary>
	public static string GetFileText (string path)
	{
		return File.ReadAllText (path);
	}

	/// <summary>
	/// 网络可用
	/// </summary>
	public static bool NetAvailable {
		get {
			return Application.internetReachability != NetworkReachability.NotReachable;
		}
	}

	/// <summary>
	/// 是否是无线
	/// </summary>
	public static bool IsWifi {
		get {
			return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork;
		}
	}

	/// <summary>
	/// 图片与byte[]互转
	/// </summary>
	/// <param name="pic">Pic.</param>
	public static Texture2D convertPNG (Texture2D pic)
	{
		byte [] data = pic.EncodeToPNG ();
		//Debug.Log("data = " + data.Length + "|" + data[0]);
		Texture2D mConvertPNG = new Texture2D (200, 200);
		mConvertPNG.LoadImage (data);

		return mConvertPNG;
	}

	/// <summary>
	/// byte[]与base64互转
	/// </summary>
	/// <returns>The to pic.</returns>
	/// <param name="base64">Base64.</param>
	public static Texture2D ByteToPic (string base64)
	{
		Texture2D pic = new Texture2D (200, 200);
		//将base64转码为byte[] 
		byte [] data = System.Convert.FromBase64String (base64);
		//加载byte[]图片
		pic.LoadImage (data);



		return pic;
	}
}